<html>
<head><meta charset="utf-8"><title>storing type as a byte array · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html">storing type as a byte array</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="215538417"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215538417" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoxc <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215538417">(Nov 04 2020 at 03:50)</a>:</h4>
<p>What are the implication for transmuting a <code>Copy</code> type to a <code>[u8; N]</code> where <code>N</code> matches it size, storing that array in memory, loading it back and transmuting it back into the correct type? The value isn't modified.</p>



<a name="215539232"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215539232" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215539232">(Nov 04 2020 at 04:10)</a>:</h4>
<p>If the array is MaybeUninit instead of u8, I believe this is just fine. There are likely additional questions though if you have references in the type, at least because you'd need to track the lifetime somehow.</p>



<a name="215539702"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215539702" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoxc <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215539702">(Nov 04 2020 at 04:18)</a>:</h4>
<p>Why <code>MaybeUninit</code>? The array has no invalid states?</p>
<p>I do also want to consider the case with references. I think that should be fine with some C models, but I wonder if stacked borrows have any complications. The type is transmuted back into the same type (with same lifetimes).</p>



<a name="215540191"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215540191" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoxc <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215540191">(Nov 04 2020 at 04:29)</a>:</h4>
<p>miri doesn't complain unless I inspect the bytes, and that's because it's unsupported</p>



<a name="215564370"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215564370" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215564370">(Nov 04 2020 at 10:37)</a>:</h4>
<p>You need [MaybeUninit&lt;u8&gt;; N] if the type has any padding between the fields (that padding would be uninitialized. Otherwise, [u8; N] is fine.</p>



<a name="215564480"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215564480" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215564480">(Nov 04 2020 at 10:39)</a>:</h4>
<p>Oh, references... going from <code>[u8; N]</code> to a &amp;'a T (or something holding one) sounds like its probably UB under stacked borrows.</p>



<a name="215565330"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215565330" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Elichai Turkel <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215565330">(Nov 04 2020 at 10:48)</a>:</h4>
<p><span class="user-mention silent" data-user-id="209168">Thom Chiovoloni</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array/near/215564480">said</a>:</p>
<blockquote>
<p>Oh, references... going from <code>[u8; N]</code> to a &amp;'a T (or something holding one) sounds like its probably UB under stacked borrows.</p>
</blockquote>
<p>Why UB? AFAIU it should be the same as <code>&amp;*(some_usize as *const T)</code>, which can be UB or not depending on T and where you got that <code>usize</code> from</p>



<a name="215566209"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215566209" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoxc <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215566209">(Nov 04 2020 at 10:58)</a>:</h4>
<p>Stacked borrows have explicit semantics for casting to a raw pointer though.</p>
<p><span class="user-mention" data-user-id="209168">@Thom Chiovoloni</span> Can you think of any examples where Miri would detect UB with casting references? At least this passes:  <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=c5be9ff8d1ec64a73d3b9b4d83770bb7">https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=c5be9ff8d1ec64a73d3b9b4d83770bb7</a></p>



<a name="215566950"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215566950" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Zoxc <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215566950">(Nov 04 2020 at 11:07)</a>:</h4>
<p>I think a more precise question is how does the operations semantics of moving or copying locals or memory differ between the array type and a reference. Also would this difference apply to a function generic over <code>T: Copy</code>?</p>



<a name="215577623"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215577623" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215577623">(Nov 04 2020 at 13:11)</a>:</h4>
<p>Hm, that's true, it probably is equivalent to going through <code>usize</code>.</p>



<a name="215705573"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215705573" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Connor Horman <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215705573">(Nov 05 2020 at 12:41)</a>:</h4>
<p>From what I've been able to derive from various discussions, that's explicitly allowed. Rust doesn't care what type the value was declared with, you can access it as whatever (provided you don't violate provenance).</p>



<a name="215764930"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215764930" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215764930">(Nov 05 2020 at 19:49)</a>:</h4>
<p>It seems unlikely that provenance will survive this process, so this should be equivalent to casting via integral types or something similarly provenance-erasing</p>



<a name="215798505"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215798505" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Connor Horman <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215798505">(Nov 06 2020 at 02:02)</a>:</h4>
<p>Ah yeah, pointers are always <em>fun</em>.</p>



<a name="215952863"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215952863" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215952863">(Nov 07 2020 at 12:29)</a>:</h4>
<p>transmuting a reference to <code>[MaybeUninit&lt;u8&gt;; PTR_SIZE]</code> and back <em>should</em> work... unlike a cast-to-usize provenance does not get erased</p>



<a name="215952910"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing%20type%20as%20a%20byte%20array/near/215952910" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/storing.20type.20as.20a.20byte.20array.html#215952910">(Nov 07 2020 at 12:30)</a>:</h4>
<p>(but Miri has some limitations when you do that and then copy the bytes 1-by-1... it can currently only preserve provenance when you copy the entire pointer at once)</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>